﻿using System;
using System.Collections.Generic;
#if DEBUG
using System.Diagnostics;
#endif // #if DEBUG
using System.Linq;
using System.Text;
using System.Threading;

using FRL.DebtChased.Repository;
using FRL.DebtChased.ServiceUtilities;

namespace FRL.DebtChased.ClockworkService
{

	/// <summary>
	/// Declaration of NewAccountWorker class
	/// </summary>
	class NewAccountWorker : BaseWorker
	{

		/////////////////////////////////////////////////////////////
		// TASKS:
		// Assign workflow to new accounts
		// Assign collectors to new accounts
		// Send the client-alert report

		/////////////////////////////////////////////////////////////
		// Implementation

		protected override string ThreadName
		{
			get { return "NewAccount"; }
		}

		protected override bool _doWork()
		{

			// Declare return variable
			bool bWorkDone = false;

			// Declare an entities object
			using (DebtChasedEntities ent = new DebtChasedEntities())
			{

				// Load the next account that has not been processed
				Account acc = Account.GetNextNewValidatedAccount(ent);
				if (acc != null)
				{

					// Log message
					_appendToLog(string.Format("Found account {0}, client ref {1}, total {2}", acc.FRLReference, acc.ClientReference, acc.CalcTotalAmount()));

					// Try to lock the account and the client
					string strLockingError = RecentActivity.AttemptLock(ent, "tbAccount", acc.AccountId, null);
					if (strLockingError == null)
						strLockingError = RecentActivity.AttemptLock(ent, "tbClient", acc.ClientId, null);
					if (strLockingError == null)
					{

						// This is a new account
						_fnWorker_processNewAccount(ent, acc);

						// Update flag
						bWorkDone = true;

					}
					else
						_appendToLog(strLockingError);

				}

			}

			// Return variable
			return bWorkDone;

		}

		/////////////////////////////////////////////////////////////
		// Operations - Worker

		private void _fnWorker_processNewAccount(DebtChasedEntities ent, Account acc)
		{

			// Declaration of local variables
			//AccountNote newNote = null;

			/*
			// Calculate the account total (ignore currencies for now)
			decimal dcTotalAmount = 0;
			foreach (AccountInvoice inv in acc.AccountInvoices)
				dcTotalAmount += inv.AmountValue;

			try
			{

				// Get the NI status id
				int iNIAccountInvoiceStatusId = 0;
				string strNIAccountInvoiceStatusName = null;
				AccountInvoiceStatus.GetNIAccountInvoiceStatus(ent, out iNIAccountInvoiceStatusId, out strNIAccountInvoiceStatusName);

				// Get the workflow id for NI status for this client
				int? iWorkflowId = ClientWorkflowAssignments.GetWorkflowId(ent, acc.ClientId, iNIAccountInvoiceStatusId);
				if (iWorkflowId == null)
					iWorkflowId = AccountInvoiceStatus.GetWorkflowId(ent, iNIAccountInvoiceStatusId);
#if DEBUG
				Debug.Assert(iWorkflowId != null);
#endif // #if DEBUG

				// If cannot lock workflow...
				string strLockingError = RecentActivity.AttemptLock(ent, "tbWorkflow", iWorkflowId, null);
				if (strLockingError != null)
				{

					// log the error
					_appendToLog(strLockingError);

				}
				else
				{

					// Get the collector for this account
					int? iCollectorId = null;
					int? iManagerId = null;
					ClientCollectorAssignments.ChooseCollectorId(ent, acc.ClientId, dcTotalAmount, out iCollectorId, out iManagerId);

					// Update the account and account-invoices
					foreach (AccountInvoice inv in acc.AccountInvoices)
					{

						// Set the NI status
						inv.AccountInvoiceStatusId = iNIAccountInvoiceStatusId;

						// Add an account-invoice note
						newNote = _createAccountNote(
							ent,
							acc,
							inv,
							string.Format("Invoice status set to {0}", strNIAccountInvoiceStatusName),
							null,
							false
						);

						// Log message
						LogFile.Append(newNote);

						// Set the workflow
						inv.WorkflowId = iWorkflowId;
						inv.WorkflowDay1 = DateTime.Now;

						// Add an account-invoice note
						newNote = _createAccountNote(
							ent,
							acc,
							inv,
							string.Format("Assigning workflow {0}", Workflow.GetName(ent, iWorkflowId.Value)),
							null,
							false
						);

						// Log message
						LogFile.Append(newNote);

					}

					// If there is a collector...
					if (iCollectorId != null)
					{

						// Set collector and manager
						acc.AssignedUserId = iCollectorId;
						acc.AssignedManagerId = iManagerId;

						// Add an account note
						newNote = _createAccountNote(
							ent,
							acc,
							null,
							string.Format("Assigning account to {0}", Contact.ComposeFullName(ent, iCollectorId.Value)),
							null,
							false
						);

						// Log message
						LogFile.Append(newNote);

					}

				}

				// Save changes to the repository
				ent.SaveChanges();

			}
			catch (Exception x)
			{

				// Load the error
				string strError = ErrorProcessing.HandleException(x, "process new account", null);

				// Load the exception
				LogFile.Append(x);

				// Add an alert to the account
				newNote = _createAccountNote(
					ent,
					acc,
					null,
					"Assigning collector and workflow to account.",
					strError,
					true
				);

			}
			 */
			
		}

		private AccountNote _createAccountNote(DebtChasedEntities ent, Account acc, AccountInvoice accountInvoice, string strNote, string strError, bool bWaitingForHuman)
		{

			// Compose flags
			AccountNote.eFlags Flags = AccountNote.eFlags.ClockworkService;
			if (bWaitingForHuman)
				Flags |= AccountNote.eFlags.WaitingForHuman;

			// Add an account-invoice note
			AccountNote Ftmp = AccountNote.CreateAccountNote(
				0,
				acc.AccountId,
				DateTime.Now,
				strNote,
				(int)Flags
			);
			if(!string.IsNullOrEmpty(strError))
				Ftmp.Error = strError;

			// If there is an invoice to add...
			if (accountInvoice != null)
			{

				// Create invoice note
				AccountNoteAccountInvoice invNote = AccountNoteAccountInvoice.CreateAccountNoteAccountInvoice( 0, 0, accountInvoice.AccountInvoiceId );
				invNote.AccountNote = Ftmp;
				//Ftmp.AccountInvoices.Add(invNote);

			}

			// Add note to entities
			ent.AccountNotes.AddObject(Ftmp);

			// Return variable
			return Ftmp;

		}

	}

}
